<?php
namespace app\common\lib;

class Http
{
    /**
     * GET请求
     * @param string $url     请求的地址
     * @param mixed  $params  传递的参数
     * @param array  $header  传递的头部参数
     * @param int    $expire  超时设置，默认30秒
     * @param mixed  $options CURL的参数
     * @return array|string
     */
    public static function get($url, $params = '', $header = [], $expire = 30, $options = [])
    {
        return self::send($url, $params, 'GET', $header, $expire, $options);
    }

    /**
     * POST请求
     * @param string $url     请求的地址
     * @param mixed  $params  传递的参数
     * @param array  $header  传递的头部参数
     * @param int    $expire  超时设置，默认30秒
     * @param mixed  $options CURL的参数
     * @return array|string
     */
    public static function post($url, $params = '', $header = [], $expire = 30, $options = [])
    {
        return self::send($url, $params, 'POST', $header, $expire, $options);
    }

    /**
     * DELETE请求
     * @param string $url     请求的地址
     * @param mixed  $params  传递的参数
     * @param array  $header  传递的头部参数
     * @param int    $expire  超时设置，默认30秒
     * @param mixed  $options CURL的参数
     * @return array|string
     */
    public static function delete($url, $params = '', $header = [], $expire = 30, $options = [])
    {
        return self::send($url, $params, 'DELETE', $header, $expire, $options);
    }

    /**
     * PUT请求
     * @param string $url     请求的地址
     * @param mixed  $params  传递的参数
     * @param array  $header  传递的头部参数
     * @param int    $expire  超时设置，默认30秒
     * @param mixed  $options CURL的参数
     * @return array|string
     */
    public static function put($url, $params = '', $header = [], $expire = 30, $options = [])
    {
        return self::send($url, $params, 'PUT', $header, $expire, $options);
    }

    /**
     * CURL发送Request请求,支持GET、POST、PUT、DELETE
     * @param string $url     请求的地址
     * @param mixed  $params  传递的参数
     * @param string $method  请求的方法
     * @param array  $header  传递的头部参数
     * @param int    $expire  超时设置，默认30秒
     * @param mixed  $options CURL的参数
     * @return array|string
     */
    private static function send($url, $params = '', $method = 'GET', $header = [], $expire = 30, $options = [])
    {
        $path = runtime_path('temp');
        $path = str_replace('\\', DIRECTORY_SEPARATOR, $path);
        $cookieFile = $path . md5(get_microsecond()) . '.txt';
        $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36';
        $ch = curl_init();
        $opt = [];
        $opt[CURLOPT_COOKIEJAR] = $cookieFile;
        $opt[CURLOPT_COOKIEFILE] = $cookieFile;
        $opt[CURLOPT_USERAGENT] = $userAgent;
        $opt[CURLOPT_CONNECTTIMEOUT] = $expire;
        $opt[CURLOPT_TIMEOUT] = $expire;
        $opt[CURLOPT_HTTPHEADER] = $header ?: ['Expect:'];
        $opt[CURLOPT_FOLLOWLOCATION] = true;
        $opt[CURLOPT_RETURNTRANSFER] = true;
        $opt[CURLOPT_VERBOSE] = true;
        if (substr($url, 0, 8) == 'https://') {
            $opt[CURLOPT_SSL_VERIFYPEER] = false;
            $opt[CURLOPT_SSL_VERIFYHOST] = 2;
        }
        if (is_array($params)) {
            $params = http_build_query($params);
        }
        switch (strtoupper($method)) {
            case 'GET':
                $extStr = (strpos($url, '?') !== false) ? '&' : '?';
                $url = $url . (($params) ? $extStr . $params : '');
                $opt[CURLOPT_URL] = $url . '?' . $params;
                break;
            case 'POST':
                $opt[CURLOPT_POST] = true;
                $opt[CURLOPT_POSTFIELDS] = $params;
                $opt[CURLOPT_URL] = $url;
                break;
            case 'PUT':
                $opt[CURLOPT_CUSTOMREQUEST] = 'PUT';
                $opt[CURLOPT_POSTFIELDS] = $params;
                $opt[CURLOPT_URL] = $url;
                break;
            case 'DELETE':
                $opt[CURLOPT_CUSTOMREQUEST] = 'DELETE';
                $opt[CURLOPT_POSTFIELDS] = $params;
                $opt[CURLOPT_URL] = $url;
                break;
            default:
                return ['error' => 0, 'msg' => '请求的方法不存在', 'info' => []];
        }
        if (!empty($options)) {
            $opt = array_merge($opt, $options);
        }
        curl_setopt_array($ch, $opt);
        $result = curl_exec($ch);
        $error = curl_error($ch);
        if ($result == false || !empty($error)) {
            $errno = curl_errno($ch);
            $info = curl_getinfo($ch);
            curl_close($ch);
            return [
                'errno' => $errno,
                'msg' => $error,
                'info' => $info,
            ];
        }
        curl_close($ch);
        return $result;
    }

    /**
     * 使用异步的方式提交
     * @param string $url  post所要提交的网址
     * @param array  $data 所要提交的数据
     * @param string $post_type 提交方式，默认表单提交
     */
    public static function asynchronousPostRequest($url, $data, $post_type = 'form')
    {
        if ($post_type == 'json') {
            //以json的方式传输数据
            $data = json_encode($data);
            $content_type = 'application/json';
        } else {
            //以form表单的方式传输数据
            $data = http_build_query($data);
            $content_type = 'application/x-www-form-urlencoded';
        }
        $len = strlen($data);
        $url_array = parse_url($url);
        if (!isset($url_array['port'])) {
            $fp = fsockopen($url_array['host'], 80, $errno, $errstr, 3);
        } else {
            $fp = fsockopen($url_array['host'], $url_array['port'], $errno, $errstr, 3);
        }
        if ($fp) {
            $out = "POST {$url_array['path']} HTTP/1.1\r\n";
            $out .= "Host: {$url_array['host']}\r\n";
            $out .= "Content-type: $content_type\r\n";
            $out .= "Content-Length: $len\r\n";
            $out .= "Connection: close\r\n";
            $out .= "\r\n";
            $out .= $data . "\r\n";
            fwrite($fp, $out);
            /* 实现异步把下面注释掉，意思是不处理返回,如要查看返回结果可打开注释 */
            //echo fread($fp, 1024);
            usleep(100);
            fclose($fp);
        }
    }
}
